package com.tticar.invmanager.service.impl;

import com.baomidou.mybatisplus.entity.Columns;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.tticar.invmanager.common.Enum.CheckStatus;
import com.tticar.invmanager.common.Enum.CodeType;
import com.tticar.invmanager.common.Enum.InReponsitoryType;
import com.tticar.invmanager.common.Enum.OutReponsitoryType;
import com.tticar.invmanager.common.utils.ServiceUtil;
import com.tticar.invmanager.common.utils.date.DateStyle;
import com.tticar.invmanager.common.utils.date.DateUtil;
import com.tticar.invmanager.entity.*;
import com.tticar.invmanager.entity.vo.CheckAddDto;
import com.tticar.invmanager.entity.vo.CheckDetailDto;
import com.tticar.invmanager.entity.vo.MyPage;
import com.tticar.invmanager.mapper.CCheckMapper;
import com.tticar.invmanager.mapper.MMaterielMapper;
import com.tticar.invmanager.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 盘点单 服务实现类
 * </p>
 *
 * @author joeyYan
 * @since 2018-08-13
 */
@Service
public class CCheckServiceImpl extends ServiceImpl<CCheckMapper, CCheck> implements ICCheckService {

    @Autowired
    IWWearhouseService wearhouseService;
    @Autowired
    ICCheckDetailService checkDetailService;
    @Autowired
    IMMaterielService materielService;
    @Autowired
    IMMaterielSkuService materielSkuService;
    @Autowired
    private ICodeCounterService codeCounterService;
    @Autowired
    private IRepositoryCountService repositoryCountService;
    @Autowired
    private IInRepositoryDetailService inRepositoryDetailService;
    @Autowired
    private IOutRepositoryDetailService outRepositoryDetailService;
    @Autowired
    private MMaterielMapper mMaterielMapper;

    @Override
    public Page selectPage(CCheck cCheck, MyPage<CCheck> page) {
        Wrapper wrapper = new EntityWrapper();
        wrapper.ne("status", 2);
        wrapper.orderBy("ctime", false);

        Columns column = Columns.create().column("*");
        column.column("total_num", "totalNum");
        column.column("(select name from w_wearhouse where id=house_id)", "houseName");
        wrapper.setSqlSelect(column);
        wrapper.like(Strings.isNotEmpty(cCheck.getCode()),cCheck.CODE, cCheck.getCode());
        wrapper.eq(cCheck.getHouseId() != null && cCheck.getHouseId() != 0 , CCheck.HOUSE_ID, cCheck.getHouseId());
        wrapper.gt(cCheck.getStartTime() != null, CCheck.CTIME, cCheck.getStartTime());
        wrapper.lt(cCheck.getEndTime() != null, CCheck.CTIME,
                DateUtil.StringToDate(DateUtil.DateToString(cCheck.getEndTime(), DateStyle.YYYY_MM_DD) + " 23:59:59", DateStyle.YYYY_MM_DD_HH_MM_SS));
        Page result = this.selectMapsPage(page, wrapper);
        return result;
    }

    @Override
    public void delete(List<Long> ids) {
        List list = new ArrayList();
        for (Long id : ids) {
            CCheck cCheck = new CCheck();
            cCheck.setId(id);
            //删除为-1，区分删除和禁用
            cCheck.setStatus(-1);
            list.add(cCheck);
        }
        this.updateBatchById(list);
    }

    @Override
    public void addCheck(Long houseId, List<CheckAddDto> list) {
        CCheck cCheck = new CCheck();
        cCheck.setHouseId(houseId);
        cCheck.setUsername(ServiceUtil.getLoginUserName());
        cCheck.setCode(codeCounterService.getOrderCode(CodeType.PD));
        cCheck.setTotalNum(list.size());
        this.insert(cCheck); // 新增盘点单

        for (CheckAddDto dto : list) {
            CCheckDetail detail = new CCheckDetail();
            detail.setUsername(ServiceUtil.getLoginUserName());
            detail.setCheckId(cCheck.getId());
            detail.setSkuId(dto.getSkuId());
            detail.setPositionId(dto.getPositionId());
            detail.setWearhouseId(houseId);
            detail.setCount(dto.getCount());
            detail.setCheckCount(dto.getCheckCount());
            detail.setRemark(dto.getRemark());
            checkDetailService.insert(detail);
        }
    }

    @Override
    @Transactional
    public String correct(Long checkId, List<CheckDetailDto> goodsList) throws ParseException {
        CCheck check = this.selectById(checkId);
        if (check.getStatus() == CheckStatus.INVALID.getCode()) {
            return "此单已作废";
        }
        if (check.getStatus() == CheckStatus.CONFIRM.getCode()) {
            return "已经校正过";
        }
        // 盘点单有盈亏的时候校正库存
        Wrapper wrapper = new EntityWrapper<>();
        wrapper.eq(CCheckDetail.CHECK_ID, checkId);
        List<CCheckDetail> detailList = checkDetailService.selectList(wrapper);

        if (CollectionUtils.isEmpty(detailList)) {
            return "无盘点明细无法校正";
        }

        //提交时数据和当前库存不一致
        List<Long> skuIdList = new ArrayList<>();
        Map<String, CheckDetailDto> keyMap = new HashMap<>();
        for(CheckDetailDto dto : goodsList) {
            String key = dto.getSkuId().toString();
            keyMap.put(key, dto);
            skuIdList.add(dto.getSkuId());
        }

        //最新库存
        wrapper = new EntityWrapper<>();
        wrapper.eq("wearhouse_id", check.getHouseId());
        wrapper.in("sku_id", skuIdList);
        List<RepositoryCount> numList = this.repositoryCountService.selectList(wrapper);
        Map<String, Integer> numMap = new HashMap<>();
        for (RepositoryCount rc : numList) {
            String key = rc.getSkuId().toString();
            numMap.put(key, rc.getCount());
        }

        for(CheckDetailDto dto : goodsList) {
            String key = dto.getSkuId().toString() ;
            if(keyMap.get(key).getCurNum() - (numMap.get(key) == null ? 0 : numMap.get(key)) != 0) {
                return "notNew";//当前库存不是最新，需要刷新页面
            }
        }

        Date orderTime = new Date();
        String username = ServiceUtil.getLoginUserName();
        String codeRK = codeCounterService.getOrderCode(CodeType.RK);
        String codeCK = codeCounterService.getOrderCode(CodeType.CK);

        // 更新状态已经校正库存
        check.setStatus(CheckStatus.CONFIRM.getCode());
        this.updateById(check);

        for (CCheckDetail detail : detailList) {
            String key = detail.getSkuId().toString();
            detail.setCount(numMap.get(key) == null ? 0 : numMap.get(key));//取最新库存
            detail.setCheckCount(keyMap.get(key).getCheckCount());//取页面提交盘点数量
            detail.setRemark(keyMap.get(key).getRemark());

            int count = detail.getCheckCount() - detail.getCount();

            //如果仓库、库位有为空的，使用默认仓库库位
//            if (check.getHouseId() == null || detail.getPositionId() == null || detail.getPositionId() == 0) {
//                MMateriel mMateriel = mMaterielMapper.queryMaterielBySkuId(detail.getSkuId());
//                check.setHouseId(mMateriel.getDefaultWhouseId());
//                detail.setPositionId(mMateriel.getDefaultPositionId());
//            }

            if(count > 0) {//盈余入库，用新的批号
//                detail.setBatchNumber(codeCounterService.getBatchCode());

                InRepositoryDetail inRepositoryDetail = new InRepositoryDetail();
                inRepositoryDetail.setCode(codeRK);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String format = sdf.format(orderTime);
                inRepositoryDetail.setOrderTime(sdf.parse(format));
                inRepositoryDetail.setUsername(username);

                inRepositoryDetail.setBuszId(detail.getId());
                inRepositoryDetail.setSkuId(detail.getSkuId());

                inRepositoryDetail.setWearhouseId(check.getHouseId());
//                inRepositoryDetail.setPositionId(detail.getPositionId());
//                inRepositoryDetail.setBatchNumber(detail.getBatchNumber());
                inRepositoryDetail.setCount(count);
                inRepositoryDetail.setRemark("盘点盈余入库");
                inRepositoryDetail.setType(InReponsitoryType.CHECK.getCode());
                inRepositoryDetailService.insert(inRepositoryDetail);
            } else if(count < 0) {//盈亏出库，按先入先出原则依次出库
                count = -count;
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String format = sdf.format(orderTime);

//                List<Map> batchList = this.inRepositoryDetailService.getBatchListByHouseId2SkuId(detail.getWearhouseId(), detail.getSkuId());
//                String house = inRepositoryDetailService.getSkuHouseByNum(detail.getSkuId(), -count, check.getHouseId());
//                String[] arr = house.split(",");
//                String batchNum = "";
//                for (int i = 0; i < arr.length; i++) {
//                    String[] arr2 = arr[i].split("_");
                List<RepositoryCount> repositoryCounts = repositoryCountService.queryOutRepositoryByHouseId(detail.getSkuId(),check.getHouseId());
                if (repositoryCounts != null && repositoryCounts.size() > 0) {
                    Integer totalNum = 0;
                    for (RepositoryCount rep : repositoryCounts) {
                        Long wearhouseId = rep.getWearhouseId();

                        Integer num = Integer.valueOf(rep.getCount() > count?count:rep.getCount());
                        totalNum += num;
                        OutRepositoryDetail outDetail = new OutRepositoryDetail();
                        outDetail.setSkuId(detail.getSkuId());
                        outDetail.setCode(codeCK);
                        outDetail.setBuszId(detail.getId());
                        outDetail.setWearhouseId(wearhouseId);
                        outDetail.setType(OutReponsitoryType.CHECK.getCode());
                        outDetail.setCount(num);
                        outDetail.setStatus(0);
                        outDetail.setCtime(new Date());
                        outDetail.setOrderTime(sdf.parse(format));
                        outDetail.setRemark("盘点亏损出库");
                        outDetail.setUsername(username);
                        //生成出库单
                        outRepositoryDetailService.insertOrUpdate(outDetail);
                        if (totalNum >= count) {
                            break;
                        }
                    }
                }

//                    batchNum += "," + batchCode;

//                }

//                }
//                detail.setBatchNumber(batchNum.substring(1));
            }

            //更新盘点明细
            this.checkDetailService.updateById(detail);

            // 更新库存
            repositoryCountService.updateRepositoryCount(detail.getSkuId(), check.getHouseId(),detail.getCheckCount() - detail.getCount());
        }
        return "";
    }
}
